package com.cal.utms.model.payment;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.cal.utms.action.user_maintenance.LoginAction;
import com.cal.utms.dao.maintenance.CustomerDaoImpl;
import com.cal.utms.dao.maintenance.IssuerDaoImpl;
import com.cal.utms.dao.maintenance.NewFundDao;
import com.cal.utms.dao.maintenance.SystemConfigurationDaoImpl;
import com.cal.utms.dao.payment.PaymentDaoImpl;
import com.cal.utms.dao.payment.ReceiptDaoImpl;
import com.cal.utms.dto.payment.PaymentDto;
import com.cal.utms.dto.payment.PaymentReceiptRequest;
import com.cal.utms.dto.payment.PaymentRequestDto;
import com.cal.utms.entity.Customer;
import com.cal.utms.entity.Fund;
import com.cal.utms.entity.Issuer;
import com.cal.utms.entity.MoneyTransaction;
import com.cal.utms.entity.Payment;
import com.cal.utms.util.Sequence;

public class PaymentModel {

	PaymentDaoImpl daoImpl = new PaymentDaoImpl();
	CustomerDaoImpl customerDaoImpl = new CustomerDaoImpl();
	IssuerDaoImpl issuerDaoImpl = new IssuerDaoImpl();
	NewFundDao fundDao = new NewFundDao();
	ReceiptDaoImpl receiptDaoImpl = new ReceiptDaoImpl();
	SystemConfigurationDaoImpl configurationDaoImpl = new SystemConfigurationDaoImpl();

	SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);

	public List<PaymentReceiptRequest> getPaymentRequest(int fundId, String date) {
		Date affectDate = new Date();
		try {
			affectDate = format.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		NewFundDao fundDao = new NewFundDao();
		List<PaymentReceiptRequest> requestDtos = new ArrayList<PaymentReceiptRequest>();
		List<PaymentRequestDto> moneyTransactions = daoImpl.getAvilabelPayments(affectDate, fundId);
		BigDecimal paymentamount = BigDecimal.ZERO;
		BigDecimal receiptamonut = BigDecimal.ZERO;
		BigDecimal balanceamount = BigDecimal.ZERO;
		for (PaymentRequestDto moneyTransaction : moneyTransactions) {
			receiptamonut = receiptDaoImpl.getTotalRecAmoutByCustomer(moneyTransaction.getCustomerCode(), moneyTransaction.getCustomerType(), fundId);
			paymentamount = daoImpl.getTotalPayAmoutByCustomer(moneyTransaction.getCustomerCode(), moneyTransaction.getCustomerType(), fundId);
			balanceamount = (moneyTransaction.getTranAmont().add(receiptamonut)).subtract(paymentamount);

			if (balanceamount.compareTo(BigDecimal.ZERO) == 1) {
				PaymentReceiptRequest paymentRequest = new PaymentReceiptRequest();
				if (moneyTransaction.getCustomerType().equals("CUS")) {
					Customer customer = customerDaoImpl.getCustomerById(moneyTransaction.getCustomerCode());
					paymentRequest.setCustomerId(customer.getId());
					paymentRequest.setCustomerCode(customer.getCode());
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCustomerName(customer.getInitials() == null ? customer.getSurname() : (customer.getInitials().concat(" " + customer.getSurname())));
					paymentRequest.setCreditBalnce(balanceamount);
				} else if (moneyTransaction.getCustomerType().equals("ISU")) {
					Issuer issuer = issuerDaoImpl.getById(moneyTransaction.getCustomerCode());
					paymentRequest.setCustomerId(issuer.getId());
					paymentRequest.setCustomerCode(issuer.getCode());
					paymentRequest.setCustomerName(issuer.getName());
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCreditBalnce(balanceamount);
				} else if (moneyTransaction.getCustomerType().equals("CTO")) {

				} else if (moneyTransaction.getCustomerType().equals("CALI")) {
					String companyName = configurationDaoImpl.getValueByPropName("companyName");
					paymentRequest.setCustomerId(0);
					paymentRequest.setCustomerCode("");
					paymentRequest.setCustomerName(companyName);
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCreditBalnce(balanceamount);
				} else if (moneyTransaction.getCustomerType().equals("FEEC")) {
					paymentRequest.setCustomerId(1);
					paymentRequest.setCustomerCode("CUSTODIAN");
					paymentRequest.setCustomerName(fundDao.getById(fundId).getCustodian().getName());
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCreditBalnce(balanceamount);
				} else {

				}
				if (paymentRequest.getCreditBalnce().compareTo(BigDecimal.ZERO) != 0) {
					requestDtos.add(paymentRequest);
					paymentamount = BigDecimal.ZERO;
					receiptamonut = BigDecimal.ZERO;
					balanceamount = BigDecimal.ZERO;
				}
			}
		}

		return requestDtos;
	}

	public void savePayments(String paymentRequests, int fundId, PaymentDto paymentDto) {
		if (paymentRequests != null) {
			Sequence seq = new Sequence();
			paymentRequests = "{ \"paymentRequests\" : ".concat(paymentRequests) + " }";
			List<Payment> payments = new ArrayList<Payment>();
			try {
				JSONObject jsonObject = new JSONObject(paymentRequests);
				JSONArray jArray = jsonObject.getJSONArray("paymentRequests");
				for (int i = 0; i < jArray.length(); i++) {
					JSONObject jObj = jArray.getJSONObject(i);
					Payment payment = new Payment();
					payment.setAmount(BigDecimal.valueOf(jObj.getDouble("amount")));
					payment.setCustomerId(jObj.getInt("customerId"));
					payment.setCustomerType(jObj.getString("customerType"));
					payment.setPaymentType(jObj.getString("paymentType"));
					payment.setPaymentNo("PAY" + seq.getNextValue("PAYEMENT"));
					payment.setFund(fundDao.getById(fundId));
					payment.setReqDate(new Date());
					payment.setReqUserId(LoginAction.getCurrentLogingUser().getId());
					payments.add(payment);
				}

				Object object = daoImpl.savePayments(payments);
				if (object instanceof Integer) {
					paymentDto.setId((Integer) object);
					paymentDto.setSuccess(true);
					paymentDto.setResulteMsg("SUCCESS");
				} else {
					paymentDto.setSuccess(false);
					paymentDto.setResulteMsg("There is some error returned from the server.");
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
	}

	public List<PaymentDto> getPaymets() {
		List<PaymentDto> receiptDtos = new ArrayList<PaymentDto>();
		List<Payment> list = daoImpl.getPayments();
		for (Payment payment : list) {
			PaymentDto dto = new PaymentDto();
			dto.setAmount(payment.getAmount().toString());
			dto.setBankAccount(payment.getBankAccount());
			dto.setBankName(payment.getBankName());
			dto.setChequeNo(payment.getChequeNo());
			dto.setConfUserId(payment.getConfUserId());
			dto.setCustomerType(payment.getCustomerType());
			dto.setCustomerId(payment.getCustomerId());
			Fund fund = payment.getFund();
			dto.setFund(fund.getId());
			dto.setFundAccount(fund.getCdsAccount());
			dto.setFundBank(fund.getCustodian().getName());
			dto.setFundName(fund.getFundCode().concat(" - " + fund.getFundName()));
			if (payment.getCustomerType().equals("CUS")) {
				Customer customer = customerDaoImpl.getCustomerById(payment.getCustomerId());
				dto.setCustomerCode(customer.getCode());
				dto.setCustomerName(customer.getDenotedByInitials().concat(" " + customer.getSurname()));
			} else if (payment.getCustomerType().equals("ISU")) {
				Issuer issuer = issuerDaoImpl.getById(payment.getCustomerId());
				dto.setCustomerCode(issuer.getCode());
				dto.setCustomerName(issuer.getName());
			} else if (payment.getCustomerType().equals("FEEC")) {
				dto.setCustomerCode("CUSTODIAN");
				dto.setCustomerName(fund.getCustodian().getName());
			}

			dto.setId(payment.getId());
			dto.setInstruction(payment.getInstruction());
			dto.setPaymentType(payment.getPaymentType());
			dto.setPurpose(payment.getPurpose());
			dto.setPaymentNo(payment.getPaymentNo());
			// dto.setReqDate(receipt.getReqDate());
			dto.setReqUserId(payment.getReqUserId());
			dto.setStatus(payment.getStatus());

			receiptDtos.add(dto);
		}
		return receiptDtos;
	}

	public void confirmPayment(int payment_id, PaymentDto paymentDto) {

		Payment payment = daoImpl.getPaymentById(payment_id);
		if (payment != null && paymentDto != null) {
			payment.setBankAccount(paymentDto.getBankAccount());
			payment.setBankName(paymentDto.getBankName());
			payment.setPurpose(paymentDto.getPurpose());
			payment.setStatus((byte) 1);
			payment.setConfDate(new Date());
			payment.setConfUserId(LoginAction.getCurrentLogingUser().getId());
			if (payment.getPaymentType().equals("C")) {
				try {
					payment.setChequeDate(format.parse(paymentDto.getChequeDate()));
				} catch (ParseException e) {
					e.printStackTrace();
				}
				payment.setChequeNo(paymentDto.getChequeNo());
				payment.setInstruction(paymentDto.getInstruction());
			}
		}
		MoneyTransactionModel model = new MoneyTransactionModel();

		List<MoneyTransaction> moneyTransactions = model.getPaymentTransaction(paymentDto, payment);

		daoImpl.confirmPayment(payment, moneyTransactions);
		paymentDto.setSuccess(true);
		paymentDto.setResulteMsg("SUCCESS");
	}

	public List<PaymentReceiptRequest> getReceiptRequest(int fund_id, String affective_date) {
		Date affectDate = new Date();
		try {
			affectDate = format.parse(affective_date);
		} catch (ParseException e) {
			e.printStackTrace();
		}

		List<PaymentReceiptRequest> requestDtos = new ArrayList<PaymentReceiptRequest>();
		List<PaymentRequestDto> moneyTransactions = daoImpl.getAvilabelPayments(affectDate, fund_id);
		BigDecimal paymentamount = BigDecimal.ZERO;
		BigDecimal receiptamonut = BigDecimal.ZERO;
		BigDecimal balanceamount = BigDecimal.ZERO;
		for (PaymentRequestDto moneyTransaction : moneyTransactions) {
			receiptamonut = receiptDaoImpl.getTotalRecAmoutByCustomer(moneyTransaction.getCustomerCode(), moneyTransaction.getCustomerType(), fund_id);
			paymentamount = daoImpl.getTotalPayAmoutByCustomer(moneyTransaction.getCustomerCode(), moneyTransaction.getCustomerType(), fund_id);
			balanceamount = (moneyTransaction.getTranAmont().add(receiptamonut)).subtract(paymentamount);

			if (balanceamount.compareTo(BigDecimal.ZERO) == -1) {
				PaymentReceiptRequest paymentRequest = new PaymentReceiptRequest();

				if (moneyTransaction.getCustomerType().equals("CUS")) {
					Customer customer = customerDaoImpl.getCustomerById(moneyTransaction.getCustomerCode());
					paymentRequest.setCustomerId(customer.getId());
					paymentRequest.setCustomerCode(customer.getCode());
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCustomerName(customer.getInitials().concat(" " + customer.getSurname()));
					paymentRequest.setCreditBalnce(balanceamount.negate());
				} else if (moneyTransaction.getCustomerType().equals("ISU")) {
					Issuer issuer = issuerDaoImpl.getById(moneyTransaction.getCustomerCode());
					paymentRequest.setCustomerId(issuer.getId());
					paymentRequest.setCustomerCode(issuer.getCode());
					paymentRequest.setCustomerName(issuer.getName());
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCreditBalnce(balanceamount.negate());
				} else if (moneyTransaction.getCustomerType().equals("CTO")) {

				} else if (moneyTransaction.getCustomerType().equals("CALI")) {
					String companyName = configurationDaoImpl.getValueByPropName("companyName");
					paymentRequest.setCustomerId(0);
					paymentRequest.setCustomerCode("");
					paymentRequest.setCustomerName(companyName);
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCreditBalnce(balanceamount);
				} else if (moneyTransaction.getCustomerType().equals("FEEC")) {
					paymentRequest.setCustomerId(00);
					paymentRequest.setCustomerCode("CUSTODIAN");
					paymentRequest.setCustomerName(fundDao.getById(fund_id).getCustodian().getName());
					paymentRequest.setCustomerType(moneyTransaction.getCustomerType());
					paymentRequest.setCreditBalnce(balanceamount);
				} else {

				}
				if (paymentRequest.getCreditBalnce().compareTo(BigDecimal.ZERO) != 0) {
					requestDtos.add(paymentRequest);
					paymentamount = BigDecimal.ZERO;
					receiptamonut = BigDecimal.ZERO;
					balanceamount = BigDecimal.ZERO;
				}
			}
		}

		return requestDtos;
	}

	public void rejecet(int payment_id, PaymentDto paymentDto) {
		Payment payment = daoImpl.getPaymentById(payment_id);
		if (payment != null) {
			payment.setBankAccount(paymentDto.getBankAccount());
			payment.setBankName(paymentDto.getBankName());
			payment.setPurpose(paymentDto.getPurpose());
			payment.setConfDate(new Date());
			payment.setConfUserId(LoginAction.getCurrentLogingUser().getId());

			if (payment.getPaymentType().equals("C")) {
				try {
					payment.setChequeDate(format.parse(paymentDto.getChequeDate()));
				} catch (ParseException e) {
					e.printStackTrace();
				}
				payment.setChequeNo(paymentDto.getChequeNo());
				payment.setInstruction(paymentDto.getInstruction());
			}

			if (payment.getStatus() == 0) {
				payment.setStatus((byte) 3);
				daoImpl.rejectPayment(payment, null);
			}
		}
	}

	public List<PaymentDto> getConfirmedPaymets() {

		List<PaymentDto> receiptDtos = new ArrayList<PaymentDto>();
		List<Payment> list = daoImpl.getConfirmedPayments();
		for (Payment payment : list) {
			PaymentDto dto = new PaymentDto();
			dto.setAmount(payment.getAmount().toString());

			dto.setCustomerType(payment.getCustomerType());
			dto.setCustomerId(payment.getCustomerId());
			if (payment.getCustomerType().equals("CUS")) {
				Customer customer = customerDaoImpl.getCustomerById(payment.getCustomerId());
				dto.setCustomerCode(customer.getCode());
				dto.setCustomerName(customer.getDenotedByInitials().concat(" " + customer.getSurname()));
			} else if (payment.getCustomerType().equals("ISU")) {
				Issuer issuer = issuerDaoImpl.getById(payment.getCustomerId());
				dto.setCustomerCode(issuer.getCode());
				dto.setCustomerName(issuer.getName());
			}
			Fund fund = payment.getFund();
			dto.setFund(fund.getId());
			dto.setFundAccount(fund.getCdsAccount());
			dto.setFundBank(fund.getCustodian().getName());
			dto.setFundName(fund.getFundCode().concat(" - " + fund.getFundName()));
			dto.setId(payment.getId());
			dto.setInstruction(payment.getInstruction());
			dto.setPaymentType(payment.getPaymentType());
			dto.setPurpose(payment.getPurpose());
			dto.setPaymentNo(payment.getPaymentNo());
			dto.setReqUserId(payment.getReqUserId());
			dto.setStatus(payment.getStatus());

			receiptDtos.add(dto);
		}
		return receiptDtos;

	}

	public void cancelPayment(int payment_id, PaymentDto paymentDto) {
		Payment payment = daoImpl.getPaymentById(payment_id);
		if (payment != null) {

			if (payment.getStatus() == 1) {
				payment.setStatus((byte) 2);
				MoneyTransactionModel model = new MoneyTransactionModel();
				List<MoneyTransaction> moneyTransactions = model.getPaymentTransactionRev(payment);
				daoImpl.rejectPayment(payment, moneyTransactions);
			}
		}
	}
}
